package com.chiyoyo.multipay.framework.core.client.dto.order;

import com.chiyoyo.multipay.framework.core.client.exception.PayException;
import com.chiyoyo.multipay.framework.core.enums.order.PayOrderDisplayModeEnum;
import com.chiyoyo.multipay.framework.core.enums.order.PayOrderStatusRespEnum;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.time.LocalDateTime;

/**
 * @author chil
 * 渠道支付订单 Response DTO
 */
@Getter
@Setter
@Accessors(chain = true)
public class PayOrderRespDTO {

    /**
     * 支付状态
     * 枚举：{@link PayOrderStatusRespEnum}
     */
    private Integer status;

    /**
     * 外部订单号
     * 对应 PayOrderExtensionDO 的 no 字段
     */
    private String outTradeNo;

    /**
     * 支付渠道编码
     */
    private String channelOrderNo;
    /**
     * 支付渠道用户编号
     */
    private String channelUserId;

    /**
     * 支付成功时间
     */
    private LocalDateTime successTime;

    /**
     * 原始的同步/异步通知结果
     */
    private Object rawData;

    // ========== 主动发起支付时，会返回的字段 ==========

    /**
     * 展示模式
     * 枚举 {@link PayOrderDisplayModeEnum} 类
     */
    private String displayMode;
    /**
     * 展示内容
     */
    private String displayContent;

    /**
     * 调用渠道的错误码
     * 注意：这里返回的是业务异常，而是不系统异常。
     * 如果是系统异常，则会抛出 {@link PayException}
     */
    private String channelErrorCode;
    /**
     * 调用渠道报错时，错误信息
     */
    private String channelErrorMsg;

    public PayOrderRespDTO() {
    }

    public String getDisplayContent(String input) {
        if ("wxV3".equals(input)) {
            if (rawData instanceof WxPayUnifiedOrderV3Result.AppResult) {
                //替换自动的key
                return displayContent.replaceAll("noncestr", "nonceStr")
                        .replaceAll("packageValue", "package");
            }
        }
        return displayContent;
    }

    /**
     * 创建一个状态为【WAITING】的订单返回对象
     *
     * @param displayMode    显示模式
     * @param displayContent 显示内容
     * @param outTradeNo     商户订单号
     * @param rawData        原始数据
     * @return 返回一个PayOrderRespDTO对象，表示状态为【WAITING】的订单返回结果
     */
    public static PayOrderRespDTO waitingOf(String displayMode, String displayContent,
                                            String outTradeNo, Object rawData) {
        PayOrderRespDTO respDTO = new PayOrderRespDTO();
        respDTO.status = PayOrderStatusRespEnum.WAITING.getStatus();
        respDTO.displayMode = displayMode;
        respDTO.displayContent = displayContent;
        // 相对通用的字段
        respDTO.outTradeNo = outTradeNo;
        respDTO.rawData = rawData;
        return respDTO;
    }

    /**
     * 创建一个状态为【SUCCESS】的订单返回对象
     *
     * @param channelOrderNo 渠道订单号
     * @param channelUserId  渠道用户ID
     * @param successTime    订单成功时间
     * @param outTradeNo     商户订单号
     * @param rawData        原始数据
     * @return 返回一个PayOrderRespDTO对象，表示状态为【SUCCESS】的订单返回结果
     */
    public static PayOrderRespDTO successOf(String channelOrderNo, String channelUserId, LocalDateTime successTime,
                                            String outTradeNo, Object rawData) {
        PayOrderRespDTO respDTO = new PayOrderRespDTO();
        respDTO.status = PayOrderStatusRespEnum.SUCCESS.getStatus();
        respDTO.channelOrderNo = channelOrderNo;
        respDTO.channelUserId = channelUserId;
        respDTO.successTime = successTime;
        // 相对通用的字段
        respDTO.outTradeNo = outTradeNo;
        respDTO.rawData = rawData;
        return respDTO;
    }

    /**
     * 创建指定状态的订单返回对象，适合支付渠道回调时使用。
     *
     * @param status         订单状态，通过PayOrderStatusRespEnum枚举定义
     * @param channelOrderNo 渠道订单号
     * @param channelUserId  渠道用户ID
     * @param successTime    订单成功时间（仅当status为成功时有效）
     * @param outTradeNo     商户订单号
     * @param rawData        原始数据，可包含支付渠道返回的任何额外信息
     * @return 返回PayOrderRespDTO对象，表示创建的订单返回对象
     */
    public static PayOrderRespDTO of(Integer status, String channelOrderNo, String channelUserId, LocalDateTime successTime,
                                     String outTradeNo, Object rawData) {
        PayOrderRespDTO respDTO = new PayOrderRespDTO();
        respDTO.status = status;
        respDTO.channelOrderNo = channelOrderNo;
        respDTO.channelUserId = channelUserId;
        respDTO.successTime = successTime;
        // 相对通用的字段
        respDTO.outTradeNo = outTradeNo;
        respDTO.rawData = rawData;
        return respDTO;
    }

    /**
     * 创建一个【CLOSED】状态的订单返回对象，适用于支付渠道调用失败时
     *
     * @param channelErrorCode 支付渠道返回的错误码
     * @param channelErrorMsg  支付渠道返回的错误信息
     * @param outTradeNo       外部订单号
     * @param rawData          原始数据，可以是任何类型
     * @return PayOrderRespDTO 订单返回对象，状态为【CLOSED】
     */
    public static PayOrderRespDTO closedOf(String channelErrorCode, String channelErrorMsg,
                                           String outTradeNo, Object rawData) {
        PayOrderRespDTO respDTO = new PayOrderRespDTO();
        respDTO.status = PayOrderStatusRespEnum.CLOSED.getStatus();
        respDTO.channelErrorCode = channelErrorCode;
        respDTO.channelErrorMsg = channelErrorMsg;
        // 相对通用的字段
        respDTO.outTradeNo = outTradeNo;
        respDTO.rawData = rawData;
        return respDTO;
    }
}
